#include "SQLParameter.h"
#include "SQLName.h"
#include "../visitor/SQLASTVisitor.h"

SQLParameter_ParameterType SQLParameter_ParameterType::DEFAULT = SQLParameter_ParameterType(1 << 0, make_string_ptr("DEFAULT"));
SQLParameter_ParameterType SQLParameter_ParameterType::IN = SQLParameter_ParameterType(1 << 1, make_string_ptr("IN"));       // in
SQLParameter_ParameterType SQLParameter_ParameterType::OUT = SQLParameter_ParameterType(1 << 2, make_string_ptr("OUT"));     // out
SQLParameter_ParameterType SQLParameter_ParameterType::INOUT = SQLParameter_ParameterType(1 << 3, make_string_ptr("INOUT")); // inout

SQLParameter_ParameterType::SQLParameter_ParameterType(uint64_t mask, string_ptr name)
{
  this->mask = mask;
  this->name = name;
}

SQLParameter_ParameterType::SQLParameter_ParameterType(SQLParameter_ParameterType *parameterType)
{
  this->mask = parameterType->mask;
  this->name = parameterType->name;
}

SQLParameter::SQLParameter()
{
  cursorParameters = std::make_shared<std::list<std::shared_ptr<SQLParameter>>>();
}

SQLExpr_ptr SQLParameter::getDefaultValue()
{
  return defaultValue;
}

void SQLParameter::setDefaultValue(SQLExpr_ptr deaultValue)
{
  if (deaultValue != nullptr)
  {
    deaultValue->setParent(SharedObject(SQLParameter));
  }
  this->defaultValue = deaultValue;
}

SQLName_ptr SQLParameter::getName()
{
  return name;
}

void SQLParameter::setName(SQLName_ptr name)
{
  if (name != nullptr)
  {
    name->setParent(SharedObject(SQLParameter));
  }
  this->name = name;
}

SQLDataType_ptr SQLParameter::getDataType()
{
  return dataType;
}

void SQLParameter::setDataType(SQLDataType_ptr dataType)
{
  if (dataType != nullptr)
  {
    dataType->setParent(SharedObject(SQLParameter));
  }
  this->dataType = dataType;
}

SQLParameter_ParameterType_ptr SQLParameter::getParamType()
{
  return paramType;
}

void SQLParameter::setParamType(SQLParameter_ParameterType_ptr paramType)
{
  this->paramType = paramType;
}

// @Override
void SQLParameter::accept0(SQLASTVisitor_ptr visitor)
{
  if (visitor->visit(SharedObject(SQLParameter)))
  {
    acceptChild(visitor, name);
    acceptChild(visitor, dataType);
    acceptChild(visitor, defaultValue);
  }
  visitor->endVisit(SharedObject(SQLParameter));
}

BOOL_ptr SQLParameter::isNoCopy()
{
  return noCopy;
}

void SQLParameter::setNoCopy(BOOL_ptr noCopy)
{
  this->noCopy = noCopy;
}

BOOL_ptr SQLParameter::isConstant()
{
  return constant;
}

void SQLParameter::setConstant(BOOL_ptr constant)
{
  this->constant = constant;
}

SQLParameter_list_ptr SQLParameter::getCursorParameters()
{
  return cursorParameters;
}

SQLName_ptr SQLParameter::getCursorName()
{
  return cursorName;
}

void SQLParameter::setCursorName(SQLName_ptr cursorName)
{
  if (cursorName != nullptr)
  {
    cursorName->setParent(SharedObject(SQLParameter));
  }
  this->cursorName = cursorName;
}

SQLObject_ptr SQLParameter::clone()
{
  SQLObject_ptr clone_tmp = std::shared_ptr<SQLParameter>(new SQLParameter());
  std::shared_ptr<SQLParameter> x = std::dynamic_pointer_cast<SQLParameter>(clone_tmp);
  // SQLParameter x = new SQLParameter();
  if (name != nullptr)
  {
    x->setName(std::dynamic_pointer_cast<SQLName>(name->clone()));
  }
  if (dataType != nullptr)
  {
    x->setDataType(std::dynamic_pointer_cast<SQLDataType>(dataType->clone()));
  }
  if (defaultValue != nullptr)
  {
    x->setDefaultValue(std::dynamic_pointer_cast<SQLExpr>(defaultValue->clone()));
  }
  x->paramType = paramType;
  x->noCopy = noCopy;
  x->constant = constant;
  x->order = order;
  x->map = map;
  if (cursorName != nullptr)
  {
    x->setCursorName(std::dynamic_pointer_cast<SQLName>(cursorName->clone()));
  }
  for (SQLParameter_ptr p : *cursorParameters)
  {
    SQLParameter_ptr p2 = std::dynamic_pointer_cast<SQLParameter>(p->clone());
    p2->setParent(x);
    x->cursorParameters->push_back(p2);
  }
  return x;
}

BOOL_ptr SQLParameter::isOrder()
{
  return order;
}

void SQLParameter::setOrder(BOOL_ptr order)
{
  this->order = order;
}

BOOL_ptr SQLParameter::isMap()
{
  return map;
}

void SQLParameter::setMap(BOOL_ptr map)
{
  this->map = map;
}

BOOL_ptr SQLParameter::isMember()
{
  return member;
}

void SQLParameter::setMember(BOOL_ptr member)
{
  this->member = member;
}
